package zzps.exeed.kernel;

import zzps.exeed.kernel.core.*;
import zzps.exeed.kernel.event.*;
import zzps.exeed.kernel.holder.AbilityHolder;
import zzps.exeed.kernel.holder.PluginHolder;

import java.util.*;
import java.util.stream.Collectors;

public class ExeedApp {

    private AppContext appContext;
    private final Class<?> source;
    private final ExeedConfig exeedConfig;
    private final ClassLoader classLoader;
    private List<PluginHolder> pluginList;

    public ExeedApp(Class<?> source, String[] args) {
        this.source = source;
        classLoader = source.getClassLoader();
        exeedConfig = new ExeedConfig(classLoader);
        exeedConfig.load(this,args);
        appContext = new AppContext(classLoader, exeedConfig);
    }

    public AppContext context() {
        return appContext;
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }

    public void start(){
        //增强能力处理
        processAbility();
        //加载插件
        scanPlugin();
        //1，应用初始化完成事件
        EventBroadcaster.broadcaster(new AppInitEndAppEvent(this));
        for (PluginHolder pluginHolder : pluginList) {
            pluginHolder.init(appContext);
        }
        pluginList.sort(PluginHolder::sort);
        //2，插件初始化完成事件
        EventBroadcaster.broadcaster(new PluginInitEndAppEvent(this));
        for (PluginHolder pluginHolder : pluginList) {
            pluginHolder.start(appContext);
        }
        //3,插件启动完成事件
        EventBroadcaster.broadcaster(new PluginStartEndAppEvent(this));
        appContext.collectPanda(source);
        //4，panda加载完成事件
        EventBroadcaster.broadcaster(new PandaLoadedAppEvent(this));
        appContext.buildPanda();
        //5,panda准备完成事件
        EventBroadcaster.broadcaster(new PandaReadyAppEvent(this));
        appContext.start();
        //6,应用加载完成事件
        EventBroadcaster.broadcaster(new AppLoadEndAppEvent(this));
    }

    public void stop(){
        for (PluginHolder pluginHolder : pluginList) {
            pluginHolder.stop();
        }
        appContext.stop();
    }
    private void scanPlugin(){
        List<String> pluginScanList = new ClassPathPluginHolderScanner(classLoader).scan();
        pluginList = pluginScanList.stream().map(s -> new PluginHolder(s, classLoader)).collect(Collectors.toList());
    }


    private void processAbility(){
        Map<String, Set<String>> setMap = new ClassPathAbilityHolderScanner(classLoader).scan();
        Set<String> implementations = setMap.get(Ability.class.getName());
        if (implementations == null){
            return;
        }
        for (String className : implementations) {
            AbilityHolder abilityHolder = new AbilityHolder(className, classLoader);
            abilityHolder.init(appContext);
        }
    }

}
